package com.draw.server.gui.panel;

import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;
import java.net.UnknownHostException;

import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.xml.ws.Endpoint;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.draw.server.bdd_manager.ColorManager;
import com.draw.server.bdd_manager.WordManager;
import com.draw.server.service.ColorService;
import com.draw.server.service.DrawingService;
import com.draw.server.service.GlobalService;
import com.draw.server.service.LineService;
import com.draw.server.service.UserService;
import com.draw.server.service.VectorService;
import com.draw.server.service.WordService;

public class HomePanel extends JPanel implements ActionListener {
	private static final long serialVersionUID = -1803225117436173342L;

	private JSpinner port;
	private JLabel ip;
	private JLabel etat;
	private JButton start;
	private JButton stop;
	private static final Logger logger = LoggerFactory.getLogger(HomePanel.class);

	private Endpoint server[];
	
	private static HomePanel instance = new HomePanel();

	public static HomePanel getInstance() {
		return instance;
	}

	public HomePanel() {
		this.server = null;
		/**/
		this.setLayout(new FlowLayout());
		JPanel pan = new JPanel(new GridLayout(4, 2));

		pan.add(new JLabel("IP :"));
		this.ip = new JLabel(this.getIp());
		pan.add(this.ip);

		pan.add(new JLabel("Port :"));
		this.port = new JSpinner(new SpinnerNumberModel(8080, 3000, 9999, 1));
		pan.add(this.port);

		pan.add(new JLabel("Etat :"));
		this.etat = new JLabel("Arrêté");
		pan.add(this.etat);

		this.start = new JButton("Start");
		this.start.addActionListener(this);
		pan.add(this.start);
		this.stop = new JButton("Stop");
		this.stop.addActionListener(this);
		this.stop.setEnabled(false);
		pan.add(this.stop);

		this.add(pan);

		this.setVisible(true);
	}
	
	

	private String getIp() {
		try {
			return InetAddress.getLocalHost().getHostAddress();
		} catch (UnknownHostException e) {
			return "localhost";
		}
	}

	private boolean checkDataBase()
	{
		boolean erreur = false;
		if(ColorManager.countColor() <= 0)
		{
			erreur = true;
			logger.error("Erreur : Aucune couleur disponible pour dessiner !");
			JOptionPane.showMessageDialog(null, "Impossible de démarer le serveur.\nAucune couleur disponible pour dessiner !\n Allez dans l'onglet Couleurs pour en ajouter !", "Erreur !", JOptionPane.ERROR_MESSAGE);
		}
		else if(WordManager.countWord() <= 0)
		{
			erreur = true;
			logger.error("Erreur : Aucune couleur disponible pour dessiner !");
			JOptionPane.showMessageDialog(null, "Impossible de démarrer le serveur !\n Aucun mot disponible !\n Allez dans l'onglet Mots pour en ajouter !", "Erreur !", JOptionPane.ERROR_MESSAGE);
		}
		for(int m = 1; m<=3 && !erreur; m++)
		{
			if(WordManager.countWordByLevel(m) <= 0)
			{
				erreur = true;
				logger.error("Erreur : Aucune couleur disponible pour dessiner !");
				JOptionPane.showMessageDialog(null, "Impossible de démarrer le serveur !\n Aucun mot disponible pour le niveau"+m+"!\n Allez dans l'onglet Mots pour en ajouter !", "Erreur !", JOptionPane.ERROR_MESSAGE);
			}
		}
		return erreur;
	}
	
	private void startAction() {
		server = null; //On recommence si le serveur n'est pas null (après, merci le garbadge collecteur)
		//if (this.server == null) {
			//on vérifie que la base de données contient au moins quelques données pour jouer dans
			//des conditions correct.
			boolean server_error = false;
			boolean bdd_error = checkDataBase();
			
			if(!bdd_error)
			{
				String uri = "http://"+this.getIp()+":" + ((Integer) this.port.getValue())
						+ "/";
				
				Object[] data = { new GlobalService(), new UserService(),
						new WordService(), new ColorService(),
						new DrawingService(), new LineService(),
						new VectorService() };
				
				this.server = new Endpoint[data.length];
				
				//Lancement des WebServices :
				for (int i = 0; i < data.length && !server_error; i++) {
					try
					{
					this.server[i] = Endpoint.publish(uri
							+ data[i].getClass().getSimpleName(), data[i]);
					logger.info("Webservice {} sarted at url {}", data[i]
							.getClass().getSimpleName(), uri);
					}
					catch(Exception e)
					{
						server_error = true;
						logger.error("Error while starting service ! May be your port are already use !\nMore informations : \n WebService : {} \n stacktrace : {} ", data[i]
								.getClass().getSimpleName(), e.getMessage());
					}
					
				}
				
				//Si tout s'est bien passé :
				if(!server_error)
				{
					JOptionPane.showMessageDialog(null, "Le serveur a été correctement démarré !", "Serveur en ligne !", JOptionPane.PLAIN_MESSAGE);
					
					//mise à jour de l'interface graphique
					this.start.setEnabled(false);
					this.port.setEnabled(false);
					
					this.etat.setText("En cours");
					this.stop.setEnabled(true);
				}
				else
				{
					JOptionPane.showMessageDialog(null, "Impossible de démarrer le serveur !\n Verifiez que le port n'est pas déjà occupé !", "Erreur !", JOptionPane.ERROR_MESSAGE);
				}

			}
		//}
	}

	private void stopAction() {
		if (this.server != null) {
			this.stop.setEnabled(false);
			for (int i = 0; i < this.server.length; i++) {
				this.server[i].stop();
			}
			this.etat.setText("Arrêté");
			this.port.setEnabled(true);
			this.start.setEnabled(true);
			this.server = null;
		}
	}
	
	/**
	 * Cette fonction permet d'arrêter le serveur depuis l'exterieur.
	 * Elle va permettre à l'objet Window (la fenetre du serveur) d'arrêter
	 * le serveur quand l'utilisateur va fermer la fenêtre.
	 */
	public void stopServer()
	{
		if (this.server != null) {
			for (int i = 0; i < this.server.length; i++) {
				this.server[i].stop();
			}
			this.server = null;
		}
	}

	public void actionPerformed(ActionEvent arg0) {
		if (this.start.equals(arg0.getSource())) {
			this.startAction();
		} else if (this.stop.equals(arg0.getSource())) {
			this.stopAction();
		}
	}
}
